home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / unix_files / CmeBSB.c < prev    next >
C/C++ Source or Header  |  2008-10-18  |  24KB  |  787 lines

  1. /* (from) $XConsortium: SmeBSB.c,v 1.16 91/03/15 15:59:41 gildea Exp $ */
  2.  
  3. /*
  4.  * Modifications Copyright 1995, 1999, 2000 by Paul Mattes.
  5.  *  Permission to use, copy, modify, and distribute this software and its
  6.  *  documentation for any purpose and without fee is hereby granted,
  7.  *  provided that the above copyright notice appear in all copies and that
  8.  *  both that copyright notice and this permission notice appear in
  9.  *  supporting documentation.
  10.  *
  11.  * Copyright 1989 Massachusetts Institute of Technology
  12.  *
  13.  * Permission to use, copy, modify, distribute, and sell this software and its
  14.  * documentation for any purpose is hereby granted without fee, provided that
  15.  * the above copyright notice appear in all copies and that both that
  16.  * copyright notice and this permission notice appear in supporting
  17.  * documentation, and that the name of M.I.T. not be used in advertising or
  18.  * publicity pertaining to distribution of the software without specific,
  19.  * written prior permission.  M.I.T. makes no representations about the
  20.  * suitability of this software for any purpose.  It is provided "as is"
  21.  * without express or implied warranty.
  22.  *
  23.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  25.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  26.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  27.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  28.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  29.  */
  30.  
  31. /*
  32.  * CmeBSB.c - Source code file for BSB Menu Entry object.
  33.  * (from) SmeBSB.c - Source code file for BSB Menu Entry object.
  34.  *
  35.  * Date:    September 26, 1989
  36.  *
  37.  * By:      Chris D. Peterson
  38.  *          MIT X Consortium 
  39.  *          kit@expo.lcs.mit.edu
  40.  */
  41.  
  42. #include "globals.h"
  43. #if defined(X3270_MENUS) /*[*/
  44.  
  45. #include <X11/IntrinsicP.h>
  46. #include <X11/StringDefs.h>
  47. #include <X11/Xos.h>
  48.  
  49. #include <X11/Xmu/Drawing.h>
  50.  
  51. #include <X11/Xaw/XawInit.h>
  52. #include "CmplxMenu.h"
  53. #include "CmeBSBP.h"
  54. #include <X11/Xaw/Cardinals.h>
  55. #include <X11/Xaw/MenuButton.h>
  56.  
  57. #include <stdio.h>
  58.  
  59. #define ONE_HUNDRED 100
  60.  
  61. #define offset(field) XtOffsetOf(CmeBSBRec, cme_bsb.field)
  62.  
  63. static XtResource resources[] = {
  64.   {XtNlabel,  XtCLabel, XtRString, sizeof(String),
  65.      offset(label), XtRString, NULL},
  66.   {XtNvertSpace,  XtCVertSpace, XtRInt, sizeof(int),
  67.      offset(vert_space), XtRImmediate, (XtPointer) 25},
  68.   {XtNleftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap),
  69.      offset(left_bitmap), XtRImmediate, (XtPointer)None},
  70.   {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
  71.      offset(justify), XtRImmediate, (XtPointer) XtJustifyLeft},
  72.   {XtNmenuName, XtCMenuName, XtRString, sizeof(String),
  73.      offset(menu_name), XtRString, NULL},
  74.   {XtNrightBitmap, XtCRightBitmap, XtRBitmap, sizeof(Pixmap),
  75.      offset(right_bitmap), XtRImmediate, (XtPointer)None},
  76.   {XtNleftMargin,  XtCHorizontalMargins, XtRDimension, sizeof(Dimension),
  77.      offset(left_margin), XtRImmediate, (XtPointer) 4},
  78.   {XtNrightMargin,  XtCHorizontalMargins, XtRDimension, sizeof(Dimension),
  79.      offset(right_margin), XtRImmediate, (XtPointer) 4},
  80.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  81.      offset(foreground), XtRString, XtDefaultForeground},
  82.   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  83.      offset(font), XtRString, XtDefaultFont},
  84. };   
  85. #undef offset
  86.  
  87. /*
  88.  * Semi Public function definitions. 
  89.  */
  90.  
  91. static void FlipColors(Widget);
  92. static void Initialize(Widget, Widget);
  93. static void Destroy(Widget);
  94. static void Redisplay(Widget, XEvent *, Region);
  95. static void FlipOn(Widget);
  96. static void FlipOff(Widget);
  97. static void PopupMenu(Widget);
  98. static void ClassInitialize(void);
  99. static Boolean SetValues(Widget, Widget, Widget);
  100. static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
  101.     XtWidgetGeometry *);
  102.  
  103. /* 
  104.  * Private Function Definitions.
  105.  */
  106.  
  107. static void GetDefaultSize(Widget, Dimension *, Dimension *);
  108. static void DrawBitmaps(Widget, GC);
  109. static void GetBitmapInfo(Widget, Boolean);
  110. static void CreateGCs(Widget);
  111. static void DestroyGCs(Widget);
  112.     
  113. #define superclass (&cmeClassRec)
  114. CmeBSBClassRec cmeBSBClassRec = {
  115.   {
  116.     /* superclass         */    (WidgetClass) superclass,
  117.     /* class_name         */    "CmeBSB",
  118.     /* size               */    sizeof(CmeBSBRec),
  119.     /* class_initializer  */    ClassInitialize,
  120.     /* class_part_initialize*/    NULL,
  121.     /* Class init'ed      */    FALSE,
  122.     /* initialize         */    (XtInitProc)Initialize,
  123.     /* initialize_hook    */    NULL,
  124.     /* realize            */    NULL,
  125.     /* actions            */    NULL,
  126.     /* num_actions        */    ZERO,
  127.     /* resources          */    resources,
  128.     /* resource_count     */    XtNumber(resources),
  129.     /* xrm_class          */    NULLQUARK,
  130.     /* compress_motion    */    FALSE, 
  131.     /* compress_exposure  */    FALSE,
  132.     /* compress_enterleave*/     FALSE,
  133.     /* visible_interest   */    FALSE,
  134.     /* destroy            */    Destroy,
  135.     /* resize             */    NULL,
  136.     /* expose             */    Redisplay,
  137.     /* set_values         */    (XtSetValuesFunc)SetValues,
  138.     /* set_values_hook    */    NULL,
  139.     /* set_values_almost  */    XtInheritSetValuesAlmost,  
  140.     /* get_values_hook    */    NULL,            
  141.     /* accept_focus       */    NULL,
  142.     /* intrinsics version */    XtVersion,
  143.     /* callback offsets   */    NULL,
  144.     /* tm_table          */    NULL,
  145.     /* query_geometry      */    QueryGeometry,
  146.     /* display_accelerator*/    NULL,
  147.     /* extension      */    NULL
  148.   },{
  149.     /* Menu Entry Fields */
  150.       
  151.     /* highlight */             FlipOn,
  152.     /* unhighlight */           FlipOff,
  153.     /* notify */        XtInheritNotify,
  154.     /* extension      */    NULL
  155.   }, {
  156.     /* BSB Menu entry Fields */  
  157.  
  158.     /* extension      */    NULL
  159.   }
  160. };
  161.  
  162. WidgetClass cmeBSBObjectClass = (WidgetClass) &cmeBSBClassRec;
  163.  
  164. /************************************************************
  165.  *
  166.  * Semi-Public Functions.
  167.  *
  168.  ************************************************************/
  169.  
  170. /*    Function Name: ClassInitialize
  171.  *    Description: Initializes the CmeBSBObject. 
  172.  *    Arguments: none.
  173.  *    Returns: none.
  174.  */
  175.  
  176. static void 
  177. ClassInitialize(void)
  178. {
  179.     XawInitializeWidgetSet();
  180.     XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0 );
  181. }
  182.  
  183. /*      Function Name: Initialize
  184.  *      Description: Initializes the complex menu widget
  185.  *      Arguments: request - the widget requested by the argument list.
  186.  *                 new     - the new widget with both resource and non
  187.  *                           resource values.
  188.  *      Returns: none.
  189.  */
  190.  
  191. static void
  192. Initialize(Widget request unused, Widget new)
  193. {
  194.     CmeBSBObject entry = (CmeBSBObject) new;
  195.  
  196.     if (entry->cme_bsb.label == NULL) 
  197.     entry->cme_bsb.label = XtName(new);
  198.     else
  199.     entry->cme_bsb.label = XtNewString( entry->cme_bsb.label );
  200.  
  201.     GetDefaultSize(new, &(entry->rectangle.width), &(entry->rectangle.height));
  202.     CreateGCs(new);
  203.  
  204.     entry->cme_bsb.left_bitmap_width = entry->cme_bsb.left_bitmap_height = 0;
  205.     entry->cme_bsb.right_bitmap_width = entry->cme_bsb.right_bitmap_height = 0;
  206.  
  207.     GetBitmapInfo(new, TRUE);    /* Left Bitmap Info */
  208.     GetBitmapInfo(new, FALSE);    /* Right Bitmap Info */
  209.  
  210.     entry->cme_bsb.ticking = False;
  211. }
  212.  
  213. /*      Function Name: Destroy
  214.  *      Description: Called at destroy time, cleans up.
  215.  *      Arguments: w - the complex menu widget.
  216.  *      Returns: none.
  217.  */
  218.  
  219. static void
  220. Destroy(Widget w)
  221. {
  222.     CmeBSBObject entry = (CmeBSBObject) w;
  223.  
  224.     DestroyGCs(w);
  225.     if (entry->cme_bsb.label != XtName(w))
  226.     XtFree(entry->cme_bsb.label);
  227.     if (entry->cme_bsb.ticking)
  228.     XtRemoveTimeOut(entry->cme_bsb.id);
  229. }
  230.  
  231. /*      Function Name: Redisplay
  232.  *      Description: Redisplays the contents of the widget.
  233.  *      Arguments: w - the complex menu widget.
  234.  *                 event - the X event that caused this redisplay.
  235.  *                 region - the region the needs to be repainted. 
  236.  *      Returns: none.
  237.  */
  238.  
  239. static void
  240. Redisplay(Widget w, XEvent *event unused, Region region unused)
  241. {
  242.     GC gc;
  243.     CmeBSBObject entry = (CmeBSBObject) w;
  244.     int    font_ascent, font_descent, y_loc;
  245.  
  246.     entry->cme_bsb.set_values_area_cleared = FALSE;    
  247.     font_ascent = entry->cme_bsb.font->max_bounds.ascent;
  248.     font_descent = entry->cme_bsb.font->max_bounds.descent;
  249.  
  250.     y_loc = entry->rectangle.y;
  251.     
  252.     if (XtIsSensitive(w) && XtIsSensitive( XtParent(w) ) ) {
  253.     if ( w == XawComplexMenuGetActiveEntry(XtParent(w)) ) {
  254.         XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), 
  255.                entry->cme_bsb.norm_gc, 0, y_loc,
  256.                (unsigned int) entry->rectangle.width,
  257.                (unsigned int) entry->rectangle.height);
  258.         gc = entry->cme_bsb.rev_gc;
  259.     }
  260.     else
  261.         gc = entry->cme_bsb.norm_gc;
  262.     }
  263.     else
  264.     gc = entry->cme_bsb.norm_gray_gc;
  265.     
  266.     if (entry->cme_bsb.label != NULL) {
  267.     int x_loc = entry->cme_bsb.left_margin;
  268.     int len = strlen(entry->cme_bsb.label);
  269.     char * label = entry->cme_bsb.label;
  270.  
  271.     switch(entry->cme_bsb.justify) {
  272.         int width, t_width;
  273.  
  274.     case XtJustifyCenter:
  275.         t_width = XTextWidth(entry->cme_bsb.font, label, len);
  276.         width = entry->rectangle.width - (entry->cme_bsb.left_margin +
  277.                           entry->cme_bsb.right_margin);
  278.         x_loc += (width - t_width)/2;
  279.         break;
  280.     case XtJustifyRight:
  281.         t_width = XTextWidth(entry->cme_bsb.font, label, len);
  282.         x_loc = entry->rectangle.width - (entry->cme_bsb.right_margin +
  283.                           t_width);
  284.         break;
  285.     case XtJustifyLeft:
  286.     default:
  287.         break;
  288.     }
  289.  
  290.     y_loc += ((int)entry->rectangle.height - 
  291.           (font_ascent + font_descent)) / 2 + font_ascent;
  292.     
  293.     XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc,
  294.             x_loc, y_loc, label, len);
  295.     }
  296.  
  297.     DrawBitmaps(w, gc);
  298. }
  299.  
  300.  
  301. /*      Function Name: SetValues
  302.  *      Description: Relayout the menu when one of the resources is changed.
  303.  *      Arguments: current - current state of the widget.
  304.  *                 request - what was requested.
  305.  *                 new - what the widget will become.
  306.  *      Returns: none
  307.  */
  308.  
  309. static Boolean
  310. SetValues(Widget current, Widget request unused, Widget new)
  311. {
  312.     CmeBSBObject entry = (CmeBSBObject) new;
  313.     CmeBSBObject old_entry = (CmeBSBObject) current;
  314.     Boolean ret_val = FALSE;
  315.  
  316.     if (old_entry->cme_bsb.label != entry->cme_bsb.label) {
  317.         if (old_entry->cme_bsb.label != XtName( new ) )
  318.         XtFree( (char *) old_entry->cme_bsb.label );
  319.  
  320.     if (entry->cme_bsb.label != XtName(new) ) 
  321.         entry->cme_bsb.label = XtNewString( entry->cme_bsb.label );
  322.  
  323.     ret_val = True;
  324.     }
  325.  
  326.     if (entry->rectangle.sensitive != old_entry->rectangle.sensitive )
  327.     ret_val = TRUE;
  328.  
  329.     if (entry->cme_bsb.left_bitmap != old_entry->cme_bsb.left_bitmap) {
  330.     GetBitmapInfo(new, TRUE);
  331.     ret_val = TRUE;
  332.     }
  333.  
  334.     if (entry->cme_bsb.right_bitmap != old_entry->cme_bsb.right_bitmap) {
  335.     GetBitmapInfo(new, FALSE);
  336.     ret_val = TRUE;
  337.     }
  338.  
  339.     if ( (old_entry->cme_bsb.font != entry->cme_bsb.font) ||
  340.      (old_entry->cme_bsb.foreground != entry->cme_bsb.foreground) ) {
  341.     DestroyGCs(current);
  342.     CreateGCs(new);
  343.     ret_val = TRUE;
  344.     }
  345.  
  346.     if (ret_val) {
  347.     GetDefaultSize(new, 
  348.                &(entry->rectangle.width), &(entry->rectangle.height));
  349.     entry->cme_bsb.set_values_area_cleared = TRUE;
  350.     }
  351.     return(ret_val);
  352. }
  353.  
  354. /*    Function Name: QueryGeometry.
  355.  *    Description: Returns the preferred geometry for this widget.
  356.  *    Arguments: w - the menu entry object.
  357.  *                 itended, return_val - the intended and return geometry info.
  358.  *    Returns: A Geometry Result.
  359.  *
  360.  * See the Intrinsics manual for details on what this function is for.
  361.  * 
  362.  * I just return the height and width of the label plus the margins.
  363.  */
  364.  
  365. static XtGeometryResult
  366. QueryGeometry(Widget w, XtWidgetGeometry *intended,
  367.     XtWidgetGeometry *return_val)
  368. {
  369.     CmeBSBObject entry = (CmeBSBObject) w;
  370.     Dimension width, height;
  371.     XtGeometryResult ret_val = XtGeometryYes;
  372.     XtGeometryMask mode = intended->request_mode;
  373.  
  374.     GetDefaultSize(w, &width, &height );    
  375.  
  376.     if ( ((mode & CWWidth) && (intended->width != width)) ||
  377.      !(mode & CWWidth) ) {
  378.     return_val->request_mode |= CWWidth;
  379.     return_val->width = width;
  380.     ret_val = XtGeometryAlmost;
  381.     }
  382.  
  383.     if ( ((mode & CWHeight) && (intended->height != height)) ||
  384.      !(mode & CWHeight) ) {
  385.     return_val->request_mode |= CWHeight;
  386.     return_val->height = height;
  387.     ret_val = XtGeometryAlmost;
  388.     }
  389.  
  390.     if (ret_val == XtGeometryAlmost) {
  391.     mode = return_val->request_mode;
  392.     
  393.     if ( ((mode & CWWidth) && (width == entry->rectangle.width)) &&
  394.          ((mode & CWHeight) && (height == entry->rectangle.height)) )
  395.         return(XtGeometryNo);
  396.     }
  397.  
  398.     return(ret_val);
  399. }
  400.  
  401. /*      Function Name: OnCallback
  402.  *      Description: Timeout callback for submenu pop-up.
  403.  *      Arguments: closure - the bsb menu entry widget.
  404.  *      Returns: none.
  405.  */
  406.  
  407. static void
  408. OnCallback(XtPointer closure, XtIntervalId *id unused)
  409. {
  410.     Widget w = (Widget) closure;
  411.     CmeBSBObject entry = (CmeBSBObject) w;
  412.  
  413.     if (entry->cme_bsb.ticking &&
  414.         XawComplexMenuGetActiveEntry(XtParent(w)) == w)
  415.     PopupMenu(w);
  416.     entry->cme_bsb.ticking = False;
  417. }
  418.  
  419. /*      Function Name: FlipOn
  420.  *      Description: Invert the colors of the current entry.
  421.  *      Arguments: w - the bsb menu entry widget.
  422.  *      Returns: none.
  423.  */
  424.  
  425. static void 
  426. FlipOn(Widget w)
  427. {
  428.     CmeBSBObject entry = (CmeBSBObject) w;
  429.  
  430.     FlipColors(w);
  431.     if (entry->cme_bsb.menu_name == NULL)
  432.     return;
  433.     if (entry->cme_bsb.ticking)
  434.     XtRemoveTimeOut(entry->cme_bsb.id);
  435.     entry->cme_bsb.ticking = True;
  436.     entry->cme_bsb.id = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
  437.         200L, OnCallback, (XtPointer)w);
  438. }
  439.  
  440. /*      Function Name: FlipOff
  441.  *      Description: Invert the colors of the current entry.
  442.  *      Arguments: w - the bsb menu entry widget.
  443.  *      Returns: none.
  444.  */
  445.  
  446. static void 
  447. FlipOff(Widget w)
  448. {
  449.     CmeBSBObject entry = (CmeBSBObject) w;
  450.     Widget menu = NULL, temp;
  451.  
  452.     FlipColors(w);
  453.     if (entry->cme_bsb.menu_name == NULL)
  454.     return;
  455.     if (entry->cme_bsb.ticking) {
  456.     XtRemoveTimeOut(entry->cme_bsb.id);
  457.     entry->cme_bsb.ticking = False;
  458.     return;
  459.     }
  460.  
  461.     temp = w;
  462.     while(temp != NULL) {
  463.     menu = XtNameToWidget(temp, entry->cme_bsb.menu_name);
  464.     if (menu == NULL) 
  465.         temp = XtParent(temp);
  466.     else
  467.         break;
  468.     }
  469.  
  470.     if (menu == NULL) {
  471.     char error_buf[BUFSIZ];
  472.     (void) sprintf(error_buf, "CmeBSB: %s %s.",
  473.         "Could not find menu widget named", entry->cme_bsb.menu_name);
  474.     XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
  475.     return;
  476.     }
  477.     XtPopdown(menu);
  478. }
  479.     
  480. /*      Function Name: FlipColors
  481.  *      Description: Invert the colors of the current entry.
  482.  *      Arguments: w - the bsb menu entry widget.
  483.  *      Returns: none.
  484.  */
  485.  
  486. static void 
  487. FlipColors(Widget w)
  488. {
  489.     CmeBSBObject entry = (CmeBSBObject) w;
  490.  
  491.     if (entry->cme_bsb.set_values_area_cleared) return;
  492.  
  493.     XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  494.            entry->cme_bsb.invert_gc, 0, (int) entry->rectangle.y,
  495.            (unsigned int) entry->rectangle.width, 
  496.            (unsigned int) entry->rectangle.height);
  497. }
  498.  
  499. /************************************************************
  500.  *
  501.  * Private Functions.
  502.  *
  503.  ************************************************************/
  504.  
  505. /*    Function Name: GetDefaultSize
  506.  *    Description: Calculates the Default (preferred) size of
  507.  *                   this menu entry.
  508.  *    Arguments: w - the menu entry widget.
  509.  *                 width, height - default sizes (RETURNED).
  510.  *    Returns: none.
  511.  */
  512.  
  513. static void
  514. GetDefaultSize(Widget w, Dimension *width, Dimension *height)
  515. {
  516.     CmeBSBObject entry = (CmeBSBObject) w;
  517.  
  518.     if (entry->cme_bsb.label == NULL) 
  519.     *width = 0;
  520.     else
  521.     *width = XTextWidth(entry->cme_bsb.font, entry->cme_bsb.label,
  522.                 strlen(entry->cme_bsb.label));
  523.  
  524.     *width += entry->cme_bsb.left_margin + entry->cme_bsb.right_margin;
  525.     
  526.     *height = (entry->cme_bsb.font->max_bounds.ascent +
  527.            entry->cme_bsb.font->max_bounds.descent);
  528.  
  529.     *height = ((int)*height * ( ONE_HUNDRED + 
  530.                     entry->cme_bsb.vert_space )) / ONE_HUNDRED;
  531. }
  532.  
  533. /*      Function Name: DrawBitmaps
  534.  *      Description: Draws left and right bitmaps.
  535.  *      Arguments: w - the complex menu widget.
  536.  *                 gc - graphics context to use for drawing.
  537.  *      Returns: none
  538.  */
  539.  
  540. static void
  541. DrawBitmaps(Widget w, GC gc)
  542. {
  543.     int x_loc, y_loc;
  544.     CmeBSBObject entry = (CmeBSBObject) w;
  545.     
  546.     if ( (entry->cme_bsb.left_bitmap == None) && 
  547.      (entry->cme_bsb.right_bitmap == None) ) return;
  548.  
  549. /*
  550.  * Draw Left Bitmap.
  551.  */
  552.  
  553.   if (entry->cme_bsb.left_bitmap != None) {
  554.     x_loc = (int)(entry->cme_bsb.left_margin -
  555.               entry->cme_bsb.left_bitmap_width) / 2;
  556.  
  557.     y_loc = entry->rectangle.y + (int)(entry->rectangle.height -
  558.                        entry->cme_bsb.left_bitmap_height) / 2;
  559.  
  560.     XCopyPlane(XtDisplayOfObject(w), entry->cme_bsb.left_bitmap,
  561.            XtWindowOfObject(w), gc, 0, 0, 
  562.            entry->cme_bsb.left_bitmap_width,
  563.            entry->cme_bsb.left_bitmap_height, x_loc, y_loc, 1);
  564.   }
  565.  
  566. /*
  567.  * Draw Right Bitmap.
  568.  */
  569.  
  570.  
  571.   if (entry->cme_bsb.right_bitmap != None) {
  572.     x_loc = entry->rectangle.width -
  573.           (int)(entry->cme_bsb.right_margin +
  574.             entry->cme_bsb.right_bitmap_width) / 2;
  575.  
  576.     y_loc = entry->rectangle.y + (int)(entry->rectangle.height -
  577.                        entry->cme_bsb.right_bitmap_height) / 2;
  578.  
  579.     XCopyPlane(XtDisplayOfObject(w), entry->cme_bsb.right_bitmap,
  580.            XtWindowOfObject(w), gc, 0, 0, 
  581.            entry->cme_bsb.right_bitmap_width,
  582.            entry->cme_bsb.right_bitmap_height, x_loc, y_loc, 1);
  583.   }
  584. }
  585.  
  586. /*      Function Name: GetBitmapInfo
  587.  *      Description: Gets the bitmap information from either of the bitmaps.
  588.  *      Arguments: w - the bsb menu entry widget.
  589.  *                 is_left - TRUE if we are testing left bitmap,
  590.  *                           FALSE if we are testing the right bitmap.
  591.  *      Returns: none
  592.  */
  593.  
  594. static void
  595. GetBitmapInfo(Widget w, Boolean is_left)
  596. {
  597.     CmeBSBObject entry = (CmeBSBObject) w;    
  598.     unsigned int depth, bw;
  599.     Window root;
  600.     int x, y;
  601.     unsigned int width, height;
  602.     char buf[BUFSIZ];
  603.     
  604.     if (is_left) {
  605.     if (entry->cme_bsb.left_bitmap != None) {
  606.         if (!XGetGeometry(XtDisplayOfObject(w), 
  607.                   entry->cme_bsb.left_bitmap, &root, 
  608.                   &x, &y, &width, &height, &bw, &depth)) {
  609.         (void) sprintf(buf, "CmeBSB Object: %s %s \"%s\".", "Could not",
  610.             "get Left Bitmap geometry information for menu entry ",
  611.             XtName(w));
  612.         XtAppError(XtWidgetToApplicationContext(w), buf);
  613.         }
  614.         if (depth != 1) {
  615.         (void) sprintf(buf, "CmeBSB Object: %s \"%s\"%s.", 
  616.             "Left Bitmap of entry ", 
  617.             XtName(w), " is not one bit deep.");
  618.         XtAppError(XtWidgetToApplicationContext(w), buf);
  619.         }
  620.         entry->cme_bsb.left_bitmap_width = (Dimension) width; 
  621.         entry->cme_bsb.left_bitmap_height = (Dimension) height;
  622.     }
  623.     }
  624.     else if (entry->cme_bsb.right_bitmap != None) {
  625.     if (!XGetGeometry(XtDisplayOfObject(w),
  626.               entry->cme_bsb.right_bitmap, &root,
  627.               &x, &y, &width, &height, &bw, &depth)) {
  628.         (void) sprintf(buf, "CmeBSB Object: %s %s \"%s\".", "Could not",
  629.             "get Right Bitmap geometry information for menu entry ",
  630.             XtName(w));
  631.         XtAppError(XtWidgetToApplicationContext(w), buf);
  632.     }
  633.     if (depth != 1) {
  634.         (void) sprintf(buf, "CmeBSB Object: %s \"%s\"%s.", 
  635.             "Right Bitmap of entry ", XtName(w),
  636.             " is not one bit deep.");
  637.         XtAppError(XtWidgetToApplicationContext(w), buf);
  638.     }
  639.     entry->cme_bsb.right_bitmap_width = (Dimension) width; 
  640.     entry->cme_bsb.right_bitmap_height = (Dimension) height;
  641.     }
  642. }      
  643.  
  644. /*      Function Name: CreateGCs
  645.  *      Description: Creates all gc's for the complex menu widget.
  646.  *      Arguments: w - the complex menu widget.
  647.  *      Returns: none.
  648.  */
  649.  
  650. static void
  651. CreateGCs(Widget w)
  652. {
  653.     CmeBSBObject entry = (CmeBSBObject) w;    
  654.     XGCValues values;
  655.     XtGCMask mask;
  656.     
  657.     values.foreground = XtParent(w)->core.background_pixel;
  658.     values.background = entry->cme_bsb.foreground;
  659.     values.font = entry->cme_bsb.font->fid;
  660.     values.graphics_exposures = FALSE;
  661.     mask        = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
  662.     entry->cme_bsb.rev_gc = XtGetGC(w, mask, &values);
  663.     
  664.     values.foreground = entry->cme_bsb.foreground;
  665.     values.background = XtParent(w)->core.background_pixel;
  666.     entry->cme_bsb.norm_gc = XtGetGC(w, mask, &values);
  667.     
  668.     values.fill_style = FillTiled;
  669.     values.tile   = XmuCreateStippledPixmap(XtScreenOfObject(w), 
  670.                         entry->cme_bsb.foreground,
  671.                         XtParent(w)->core.background_pixel,
  672.                         XtParent(w)->core.depth);
  673.     values.graphics_exposures = FALSE;
  674.     mask |= GCTile | GCFillStyle;
  675.     entry->cme_bsb.norm_gray_gc = XtGetGC(w, mask, &values);
  676.     
  677.     values.foreground ^= values.background;
  678.     values.background = 0;
  679.     values.function = GXxor;
  680.     mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction;
  681.     entry->cme_bsb.invert_gc = XtGetGC(w, mask, &values);
  682. }
  683.  
  684. /*      Function Name: DestroyGCs
  685.  *      Description: Removes all gc's for the complex menu widget.
  686.  *      Arguments: w - the complex menu widget.
  687.  *      Returns: none.
  688.  */
  689.  
  690. static void
  691. DestroyGCs(Widget w)
  692. {
  693.     CmeBSBObject entry = (CmeBSBObject) w;    
  694.  
  695.     XtReleaseGC(w, entry->cme_bsb.norm_gc);
  696.     XtReleaseGC(w, entry->cme_bsb.norm_gray_gc);
  697.     XtReleaseGC(w, entry->cme_bsb.rev_gc);
  698.     XtReleaseGC(w, entry->cme_bsb.invert_gc);
  699. }
  700.  
  701. /*      Function Name: PopupMenu
  702.  *      Description: Pops up the pullright menu associated with this widget.
  703.  *      Arguments: w - the complex menu widget.
  704.  *      Returns: none.
  705.  */
  706.  
  707. static void
  708. PopupMenu(Widget w)
  709. {
  710.     CmeBSBObject entry = (CmeBSBObject) w;
  711.     Widget menu = NULL, temp;
  712.     Arg arglist[3];
  713.     Cardinal num_args;
  714.     int menu_x, menu_y, menu_width, menu_height, button_width;
  715.     Position button_x, button_y;
  716.  
  717.     temp = w;
  718.     while(temp != NULL) {
  719.     menu = XtNameToWidget(temp, entry->cme_bsb.menu_name);
  720.     if (menu == NULL) 
  721.         temp = XtParent(temp);
  722.     else
  723.         break;
  724.     }
  725.  
  726.     if (menu == NULL) {
  727.     char error_buf[BUFSIZ];
  728.     (void) sprintf(error_buf, "CmeBSB: %s %s.",
  729.         "Could not find menu widget named", entry->cme_bsb.menu_name);
  730.     XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
  731.     return;
  732.     }
  733.     if (!XtIsRealized(menu))
  734.     XtRealizeWidget(menu);
  735.  
  736.     menu_width = menu->core.width + 2 * menu->core.border_width;
  737.     button_width = w->core.width + 2 * w->core.border_width;
  738.     menu_height = menu->core.height + 2 * menu->core.border_width;
  739.  
  740.     XtTranslateCoords(w, 0, 0, &button_x, &button_y);
  741.     menu_x = button_x + button_width + menu->core.border_width - 10; /* XXX */
  742.     menu_y = button_y + 1;
  743.  
  744.     if (menu_x >= 0) {
  745.     int scr_width = WidthOfScreen(XtScreen(menu));
  746.     if (menu_x + menu_width > scr_width)
  747.         menu_x = scr_width - menu_width;
  748.     }
  749.     if (menu_x < 0) 
  750.     menu_x = 0;
  751.  
  752.     if (menu_y >= 0) {
  753.     int scr_height = HeightOfScreen(XtScreen(menu));
  754.     if (menu_y + menu_height > scr_height)
  755.         menu_y = scr_height - menu_height;
  756.     }
  757.     if (menu_y < 0)
  758.     menu_y = 0;
  759.  
  760.     num_args = 0;
  761.     XtSetArg(arglist[num_args], XtNx, menu_x); num_args++;
  762.     XtSetArg(arglist[num_args], XtNy, menu_y); num_args++;
  763.     XtSetArg(arglist[num_args], XtNcMparent, XtParent(w)); num_args++;
  764.     XtSetValues(menu, arglist, num_args);
  765.  
  766.     XtPopup(menu, XtGrabNonexclusive);
  767. }
  768.  
  769. #ifdef apollo
  770.  
  771. /*
  772.  * The apollo compiler that we have optimizes out my code for
  773.  * FlipColors() since it is static. and no one executes it in this
  774.  * file.  I am setting the function pointer into the class structure so
  775.  * that it can be called by my parent who will tell me to when to
  776.  * highlight and unhighlight.
  777.  */
  778.  
  779. void
  780. _XawCmeBSBApolloHack(void)
  781. {
  782.     FlipColors();
  783. }
  784. #endif /* apollo */
  785.  
  786. #endif /*]*/
  787.